{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "b6ee1ede",
   "metadata": {},
   "source": [
    "## Voice Style Control Demo"
   ]
  },
  {
   "cell_type": "code",
   "id": "b7f043ee",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-05-11T18:39:27.030966Z",
     "start_time": "2024-05-11T18:39:27.015342Z"
    }
   },
   "source": [
    "import os\n",
    "import torch\n",
    "from openvoice import se_extractor\n",
    "from openvoice.api import BaseSpeakerTTS, ToneColorConverter"
   ],
   "outputs": [],
   "execution_count": 12
  },
  {
   "cell_type": "markdown",
   "id": "15116b59",
   "metadata": {},
   "source": [
    "### Initialization"
   ]
  },
  {
   "cell_type": "code",
   "id": "aacad912",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-05-11T18:39:28.091306Z",
     "start_time": "2024-05-11T18:39:27.030966Z"
    }
   },
   "source": [
    "ckpt_base = 'checkpoints/base_speakers/EN'\n",
    "ckpt_converter = 'checkpoints/converter'\n",
    "device=\"cuda:0\" if torch.cuda.is_available() else \"cpu\"\n",
    "output_dir = 'outputs'\n",
    "\n",
    "base_speaker_tts = BaseSpeakerTTS(f'{ckpt_base}/config.json', device=device)\n",
    "base_speaker_tts.load_ckpt(f'{ckpt_base}/checkpoint.pth')\n",
    "\n",
    "tone_color_converter = ToneColorConverter(f'{ckpt_converter}/config.json', device=device)\n",
    "tone_color_converter.load_ckpt(f'{ckpt_converter}/checkpoint.pth')\n",
    "\n",
    "os.makedirs(output_dir, exist_ok=True)"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Loaded checkpoint 'checkpoints/base_speakers/EN/checkpoint.pth'\n",
      "missing/unexpected keys: [] []\n",
      "Loaded checkpoint 'checkpoints/converter/checkpoint.pth'\n",
      "missing/unexpected keys: [] []\n"
     ]
    }
   ],
   "execution_count": 13
  },
  {
   "cell_type": "markdown",
   "id": "7f67740c",
   "metadata": {},
   "source": [
    "### Obtain Tone Color Embedding"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f8add279",
   "metadata": {},
   "source": [
    "The `source_se` is the tone color embedding of the base speaker. \n",
    "It is an average of multiple sentences generated by the base speaker. We directly provide the result here but\n",
    "the readers feel free to extract `source_se` by themselves."
   ]
  },
  {
   "cell_type": "code",
   "id": "63ff6273",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-05-11T18:39:28.107184Z",
     "start_time": "2024-05-11T18:39:28.091559Z"
    }
   },
   "source": [
    "source_se = torch.load(f'{ckpt_base}/en_default_se.pth').to(device)"
   ],
   "outputs": [],
   "execution_count": 14
  },
  {
   "cell_type": "markdown",
   "id": "4f71fcc3",
   "metadata": {},
   "source": [
    "The `reference_speaker.mp3` below points to the short audio clip of the reference whose voice we want to clone. We provide an example here. If you use your own reference speakers, please **make sure each speaker has a unique filename.** The `se_extractor` will save the `targeted_se` using the filename of the audio and **will not automatically overwrite.**"
   ]
  },
  {
   "cell_type": "code",
   "id": "55105eae",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-05-11T18:43:23.721477Z",
     "start_time": "2024-05-11T18:43:23.596431Z"
    }
   },
   "source": [
    "reference_speaker = 'resources/example_reference.mp3' # This is the voice you want to clone\n",
    "target_se, audio_name = se_extractor.get_se(reference_speaker, tone_color_converter, target_dir='processed', vad=True)"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "OpenVoice version: v1\n"
     ]
    },
    {
     "ename": "FileNotFoundError",
     "evalue": "[WinError 2] 系统找不到指定的文件。",
     "output_type": "error",
     "traceback": [
      "\u001B[1;31m---------------------------------------------------------------------------\u001B[0m",
      "\u001B[1;31mFileNotFoundError\u001B[0m                         Traceback (most recent call last)",
      "Cell \u001B[1;32mIn[16], line 2\u001B[0m\n\u001B[0;32m      1\u001B[0m reference_speaker \u001B[38;5;241m=\u001B[39m \u001B[38;5;124m'\u001B[39m\u001B[38;5;124mresources/example_reference.mp3\u001B[39m\u001B[38;5;124m'\u001B[39m \u001B[38;5;66;03m# This is the voice you want to clone\u001B[39;00m\n\u001B[1;32m----> 2\u001B[0m target_se, audio_name \u001B[38;5;241m=\u001B[39m \u001B[43mse_extractor\u001B[49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mget_se\u001B[49m\u001B[43m(\u001B[49m\u001B[43mreference_speaker\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mtone_color_converter\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mtarget_dir\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[38;5;124;43m'\u001B[39;49m\u001B[38;5;124;43mprocessed\u001B[39;49m\u001B[38;5;124;43m'\u001B[39;49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mvad\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[38;5;28;43;01mTrue\u001B[39;49;00m\u001B[43m)\u001B[49m\n",
      "File \u001B[1;32mD:\\dev\\code\\OpenVoice\\openvoice\\se_extractor.py:144\u001B[0m, in \u001B[0;36mget_se\u001B[1;34m(audio_path, vc_model, target_dir, vad)\u001B[0m\n\u001B[0;32m    137\u001B[0m \u001B[38;5;66;03m# if os.path.isfile(se_path):\u001B[39;00m\n\u001B[0;32m    138\u001B[0m \u001B[38;5;66;03m#     se = torch.load(se_path).to(device)\u001B[39;00m\n\u001B[0;32m    139\u001B[0m \u001B[38;5;66;03m#     return se, audio_name\u001B[39;00m\n\u001B[0;32m    140\u001B[0m \u001B[38;5;66;03m# if os.path.isdir(audio_path):\u001B[39;00m\n\u001B[0;32m    141\u001B[0m \u001B[38;5;66;03m#     wavs_folder = audio_path\u001B[39;00m\n\u001B[0;32m    143\u001B[0m \u001B[38;5;28;01mif\u001B[39;00m vad:\n\u001B[1;32m--> 144\u001B[0m     wavs_folder \u001B[38;5;241m=\u001B[39m \u001B[43msplit_audio_vad\u001B[49m\u001B[43m(\u001B[49m\u001B[43maudio_path\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mtarget_dir\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[43mtarget_dir\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43maudio_name\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[43maudio_name\u001B[49m\u001B[43m)\u001B[49m\n\u001B[0;32m    145\u001B[0m \u001B[38;5;28;01melse\u001B[39;00m:\n\u001B[0;32m    146\u001B[0m     wavs_folder \u001B[38;5;241m=\u001B[39m split_audio_whisper(audio_path, target_dir\u001B[38;5;241m=\u001B[39mtarget_dir, audio_name\u001B[38;5;241m=\u001B[39maudio_name)\n",
      "File \u001B[1;32mD:\\dev\\code\\OpenVoice\\openvoice\\se_extractor.py:79\u001B[0m, in \u001B[0;36msplit_audio_vad\u001B[1;34m(audio_path, audio_name, target_dir, split_seconds)\u001B[0m\n\u001B[0;32m     77\u001B[0m \u001B[38;5;28;01mdef\u001B[39;00m \u001B[38;5;21msplit_audio_vad\u001B[39m(audio_path, audio_name, target_dir, split_seconds\u001B[38;5;241m=\u001B[39m\u001B[38;5;241m10.0\u001B[39m):\n\u001B[0;32m     78\u001B[0m     SAMPLE_RATE \u001B[38;5;241m=\u001B[39m \u001B[38;5;241m16000\u001B[39m\n\u001B[1;32m---> 79\u001B[0m     audio_vad \u001B[38;5;241m=\u001B[39m \u001B[43mget_audio_tensor\u001B[49m\u001B[43m(\u001B[49m\u001B[43maudio_path\u001B[49m\u001B[43m)\u001B[49m\n\u001B[0;32m     80\u001B[0m     segments \u001B[38;5;241m=\u001B[39m get_vad_segments(\n\u001B[0;32m     81\u001B[0m         audio_vad,\n\u001B[0;32m     82\u001B[0m         output_sample\u001B[38;5;241m=\u001B[39m\u001B[38;5;28;01mTrue\u001B[39;00m,\n\u001B[1;32m   (...)\u001B[0m\n\u001B[0;32m     85\u001B[0m         method\u001B[38;5;241m=\u001B[39m\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124msilero\u001B[39m\u001B[38;5;124m\"\u001B[39m,\n\u001B[0;32m     86\u001B[0m     )\n\u001B[0;32m     87\u001B[0m     segments \u001B[38;5;241m=\u001B[39m [(seg[\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mstart\u001B[39m\u001B[38;5;124m\"\u001B[39m], seg[\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mend\u001B[39m\u001B[38;5;124m\"\u001B[39m]) \u001B[38;5;28;01mfor\u001B[39;00m seg \u001B[38;5;129;01min\u001B[39;00m segments]\n",
      "File \u001B[1;32mD:\\dev\\code\\OpenVoice\\venv\\lib\\site-packages\\whisper_timestamped\\transcribe.py:1265\u001B[0m, in \u001B[0;36mget_audio_tensor\u001B[1;34m(audio, device)\u001B[0m\n\u001B[0;32m   1263\u001B[0m \u001B[38;5;28;01mdef\u001B[39;00m \u001B[38;5;21mget_audio_tensor\u001B[39m(audio, device\u001B[38;5;241m=\u001B[39m\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mcpu\u001B[39m\u001B[38;5;124m\"\u001B[39m):\n\u001B[0;32m   1264\u001B[0m     \u001B[38;5;28;01mif\u001B[39;00m \u001B[38;5;28misinstance\u001B[39m(audio, \u001B[38;5;28mstr\u001B[39m):\n\u001B[1;32m-> 1265\u001B[0m         audio \u001B[38;5;241m=\u001B[39m \u001B[43mwhisper\u001B[49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mload_audio\u001B[49m\u001B[43m(\u001B[49m\u001B[43maudio\u001B[49m\u001B[43m)\u001B[49m\n\u001B[0;32m   1266\u001B[0m     \u001B[38;5;28;01mif\u001B[39;00m \u001B[38;5;28misinstance\u001B[39m(audio, np\u001B[38;5;241m.\u001B[39mndarray):\n\u001B[0;32m   1267\u001B[0m         audio \u001B[38;5;241m=\u001B[39m torch\u001B[38;5;241m.\u001B[39mTensor(audio)\n",
      "File \u001B[1;32mD:\\dev\\code\\OpenVoice\\venv\\lib\\site-packages\\whisper\\audio.py:58\u001B[0m, in \u001B[0;36mload_audio\u001B[1;34m(file, sr)\u001B[0m\n\u001B[0;32m     56\u001B[0m \u001B[38;5;66;03m# fmt: on\u001B[39;00m\n\u001B[0;32m     57\u001B[0m \u001B[38;5;28;01mtry\u001B[39;00m:\n\u001B[1;32m---> 58\u001B[0m     out \u001B[38;5;241m=\u001B[39m \u001B[43mrun\u001B[49m\u001B[43m(\u001B[49m\u001B[43mcmd\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mcapture_output\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[38;5;28;43;01mTrue\u001B[39;49;00m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mcheck\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[38;5;28;43;01mTrue\u001B[39;49;00m\u001B[43m)\u001B[49m\u001B[38;5;241m.\u001B[39mstdout\n\u001B[0;32m     59\u001B[0m \u001B[38;5;28;01mexcept\u001B[39;00m CalledProcessError \u001B[38;5;28;01mas\u001B[39;00m e:\n\u001B[0;32m     60\u001B[0m     \u001B[38;5;28;01mraise\u001B[39;00m \u001B[38;5;167;01mRuntimeError\u001B[39;00m(\u001B[38;5;124mf\u001B[39m\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mFailed to load audio: \u001B[39m\u001B[38;5;132;01m{\u001B[39;00me\u001B[38;5;241m.\u001B[39mstderr\u001B[38;5;241m.\u001B[39mdecode()\u001B[38;5;132;01m}\u001B[39;00m\u001B[38;5;124m\"\u001B[39m) \u001B[38;5;28;01mfrom\u001B[39;00m \u001B[38;5;21;01me\u001B[39;00m\n",
      "File \u001B[1;32mD:\\dev\\env\\Python310\\lib\\subprocess.py:503\u001B[0m, in \u001B[0;36mrun\u001B[1;34m(input, capture_output, timeout, check, *popenargs, **kwargs)\u001B[0m\n\u001B[0;32m    500\u001B[0m     kwargs[\u001B[38;5;124m'\u001B[39m\u001B[38;5;124mstdout\u001B[39m\u001B[38;5;124m'\u001B[39m] \u001B[38;5;241m=\u001B[39m PIPE\n\u001B[0;32m    501\u001B[0m     kwargs[\u001B[38;5;124m'\u001B[39m\u001B[38;5;124mstderr\u001B[39m\u001B[38;5;124m'\u001B[39m] \u001B[38;5;241m=\u001B[39m PIPE\n\u001B[1;32m--> 503\u001B[0m \u001B[38;5;28;01mwith\u001B[39;00m Popen(\u001B[38;5;241m*\u001B[39mpopenargs, \u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mkwargs) \u001B[38;5;28;01mas\u001B[39;00m process:\n\u001B[0;32m    504\u001B[0m     \u001B[38;5;28;01mtry\u001B[39;00m:\n\u001B[0;32m    505\u001B[0m         stdout, stderr \u001B[38;5;241m=\u001B[39m process\u001B[38;5;241m.\u001B[39mcommunicate(\u001B[38;5;28minput\u001B[39m, timeout\u001B[38;5;241m=\u001B[39mtimeout)\n",
      "File \u001B[1;32mD:\\dev\\env\\Python310\\lib\\subprocess.py:971\u001B[0m, in \u001B[0;36mPopen.__init__\u001B[1;34m(self, args, bufsize, executable, stdin, stdout, stderr, preexec_fn, close_fds, shell, cwd, env, universal_newlines, startupinfo, creationflags, restore_signals, start_new_session, pass_fds, user, group, extra_groups, encoding, errors, text, umask, pipesize)\u001B[0m\n\u001B[0;32m    967\u001B[0m         \u001B[38;5;28;01mif\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mtext_mode:\n\u001B[0;32m    968\u001B[0m             \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mstderr \u001B[38;5;241m=\u001B[39m io\u001B[38;5;241m.\u001B[39mTextIOWrapper(\u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mstderr,\n\u001B[0;32m    969\u001B[0m                     encoding\u001B[38;5;241m=\u001B[39mencoding, errors\u001B[38;5;241m=\u001B[39merrors)\n\u001B[1;32m--> 971\u001B[0m     \u001B[38;5;28;43mself\u001B[39;49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43m_execute_child\u001B[49m\u001B[43m(\u001B[49m\u001B[43margs\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mexecutable\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mpreexec_fn\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mclose_fds\u001B[49m\u001B[43m,\u001B[49m\n\u001B[0;32m    972\u001B[0m \u001B[43m                        \u001B[49m\u001B[43mpass_fds\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mcwd\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43menv\u001B[49m\u001B[43m,\u001B[49m\n\u001B[0;32m    973\u001B[0m \u001B[43m                        \u001B[49m\u001B[43mstartupinfo\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mcreationflags\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mshell\u001B[49m\u001B[43m,\u001B[49m\n\u001B[0;32m    974\u001B[0m \u001B[43m                        \u001B[49m\u001B[43mp2cread\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mp2cwrite\u001B[49m\u001B[43m,\u001B[49m\n\u001B[0;32m    975\u001B[0m \u001B[43m                        \u001B[49m\u001B[43mc2pread\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mc2pwrite\u001B[49m\u001B[43m,\u001B[49m\n\u001B[0;32m    976\u001B[0m \u001B[43m                        \u001B[49m\u001B[43merrread\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43merrwrite\u001B[49m\u001B[43m,\u001B[49m\n\u001B[0;32m    977\u001B[0m \u001B[43m                        \u001B[49m\u001B[43mrestore_signals\u001B[49m\u001B[43m,\u001B[49m\n\u001B[0;32m    978\u001B[0m \u001B[43m                        \u001B[49m\u001B[43mgid\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mgids\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43muid\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mumask\u001B[49m\u001B[43m,\u001B[49m\n\u001B[0;32m    979\u001B[0m \u001B[43m                        \u001B[49m\u001B[43mstart_new_session\u001B[49m\u001B[43m)\u001B[49m\n\u001B[0;32m    980\u001B[0m \u001B[38;5;28;01mexcept\u001B[39;00m:\n\u001B[0;32m    981\u001B[0m     \u001B[38;5;66;03m# Cleanup if the child failed starting.\u001B[39;00m\n\u001B[0;32m    982\u001B[0m     \u001B[38;5;28;01mfor\u001B[39;00m f \u001B[38;5;129;01min\u001B[39;00m \u001B[38;5;28mfilter\u001B[39m(\u001B[38;5;28;01mNone\u001B[39;00m, (\u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mstdin, \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mstdout, \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mstderr)):\n",
      "File \u001B[1;32mD:\\dev\\env\\Python310\\lib\\subprocess.py:1456\u001B[0m, in \u001B[0;36mPopen._execute_child\u001B[1;34m(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, unused_restore_signals, unused_gid, unused_gids, unused_uid, unused_umask, unused_start_new_session)\u001B[0m\n\u001B[0;32m   1454\u001B[0m \u001B[38;5;66;03m# Start the process\u001B[39;00m\n\u001B[0;32m   1455\u001B[0m \u001B[38;5;28;01mtry\u001B[39;00m:\n\u001B[1;32m-> 1456\u001B[0m     hp, ht, pid, tid \u001B[38;5;241m=\u001B[39m \u001B[43m_winapi\u001B[49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mCreateProcess\u001B[49m\u001B[43m(\u001B[49m\u001B[43mexecutable\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43margs\u001B[49m\u001B[43m,\u001B[49m\n\u001B[0;32m   1457\u001B[0m \u001B[43m                             \u001B[49m\u001B[38;5;66;43;03m# no special security\u001B[39;49;00m\n\u001B[0;32m   1458\u001B[0m \u001B[43m                             \u001B[49m\u001B[38;5;28;43;01mNone\u001B[39;49;00m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[38;5;28;43;01mNone\u001B[39;49;00m\u001B[43m,\u001B[49m\n\u001B[0;32m   1459\u001B[0m \u001B[43m                             \u001B[49m\u001B[38;5;28;43mint\u001B[39;49m\u001B[43m(\u001B[49m\u001B[38;5;129;43;01mnot\u001B[39;49;00m\u001B[43m \u001B[49m\u001B[43mclose_fds\u001B[49m\u001B[43m)\u001B[49m\u001B[43m,\u001B[49m\n\u001B[0;32m   1460\u001B[0m \u001B[43m                             \u001B[49m\u001B[43mcreationflags\u001B[49m\u001B[43m,\u001B[49m\n\u001B[0;32m   1461\u001B[0m \u001B[43m                             \u001B[49m\u001B[43menv\u001B[49m\u001B[43m,\u001B[49m\n\u001B[0;32m   1462\u001B[0m \u001B[43m                             \u001B[49m\u001B[43mcwd\u001B[49m\u001B[43m,\u001B[49m\n\u001B[0;32m   1463\u001B[0m \u001B[43m                             \u001B[49m\u001B[43mstartupinfo\u001B[49m\u001B[43m)\u001B[49m\n\u001B[0;32m   1464\u001B[0m \u001B[38;5;28;01mfinally\u001B[39;00m:\n\u001B[0;32m   1465\u001B[0m     \u001B[38;5;66;03m# Child is launched. Close the parent's copy of those pipe\u001B[39;00m\n\u001B[0;32m   1466\u001B[0m     \u001B[38;5;66;03m# handles that only the child should have open.  You need\u001B[39;00m\n\u001B[1;32m   (...)\u001B[0m\n\u001B[0;32m   1469\u001B[0m     \u001B[38;5;66;03m# pipe will not close when the child process exits and the\u001B[39;00m\n\u001B[0;32m   1470\u001B[0m     \u001B[38;5;66;03m# ReadFile will hang.\u001B[39;00m\n\u001B[0;32m   1471\u001B[0m     \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_close_pipe_fds(p2cread, p2cwrite,\n\u001B[0;32m   1472\u001B[0m                          c2pread, c2pwrite,\n\u001B[0;32m   1473\u001B[0m                          errread, errwrite)\n",
      "\u001B[1;31mFileNotFoundError\u001B[0m: [WinError 2] 系统找不到指定的文件。"
     ]
    }
   ],
   "execution_count": 16
  },
  {
   "cell_type": "markdown",
   "id": "a40284aa",
   "metadata": {},
   "source": [
    "### Inference"
   ]
  },
  {
   "cell_type": "code",
   "id": "73dc1259",
   "metadata": {},
   "source": [
    "save_path = f'{output_dir}/output_en_default.wav'\n",
    "\n",
    "# Run the base speaker tts\n",
    "text = \"This audio is generated by OpenVoice.\"\n",
    "src_path = f'{output_dir}/tmp.wav'\n",
    "base_speaker_tts.tts(text, src_path, speaker='default', language='English', speed=1.0)\n",
    "\n",
    "# Run the tone color converter\n",
    "encode_message = \"@MyShell\"\n",
    "tone_color_converter.convert(\n",
    "    audio_src_path=src_path, \n",
    "    src_se=source_se, \n",
    "    tgt_se=target_se, \n",
    "    output_path=save_path,\n",
    "    message=encode_message)"
   ],
   "outputs": [],
   "execution_count": null
  },
  {
   "cell_type": "markdown",
   "id": "6e3ea28a",
   "metadata": {},
   "source": [
    "**Try with different styles and speed.** The style can be controlled by the `speaker` parameter in the `base_speaker_tts.tts` method. Available choices: friendly, cheerful, excited, sad, angry, terrified, shouting, whispering. Note that the tone color embedding need to be updated. The speed can be controlled by the `speed` parameter. Let's try whispering with speed 0.9."
   ]
  },
  {
   "cell_type": "code",
   "id": "fd022d38",
   "metadata": {},
   "source": [
    "source_se = torch.load(f'{ckpt_base}/en_style_se.pth').to(device)\n",
    "save_path = f'{output_dir}/output_whispering.wav'\n",
    "\n",
    "# Run the base speaker tts\n",
    "text = \"This audio is generated by OpenVoice.\"\n",
    "src_path = f'{output_dir}/tmp.wav'\n",
    "base_speaker_tts.tts(text, src_path, speaker='whispering', language='English', speed=0.9)\n",
    "\n",
    "# Run the tone color converter\n",
    "encode_message = \"@MyShell\"\n",
    "tone_color_converter.convert(\n",
    "    audio_src_path=src_path, \n",
    "    src_se=source_se, \n",
    "    tgt_se=target_se, \n",
    "    output_path=save_path,\n",
    "    message=encode_message)"
   ],
   "outputs": [],
   "execution_count": null
  },
  {
   "cell_type": "markdown",
   "id": "5fcfc70b",
   "metadata": {},
   "source": [
    "**Try with different languages.** OpenVoice can achieve multi-lingual voice cloning by simply replace the base speaker. We provide an example with a Chinese base speaker here and we encourage the readers to try `demo_part2.ipynb` for a detailed demo."
   ]
  },
  {
   "cell_type": "code",
   "id": "a71d1387",
   "metadata": {},
   "source": [
    "\n",
    "ckpt_base = 'checkpoints/base_speakers/ZH'\n",
    "base_speaker_tts = BaseSpeakerTTS(f'{ckpt_base}/config.json', device=device)\n",
    "base_speaker_tts.load_ckpt(f'{ckpt_base}/checkpoint.pth')\n",
    "\n",
    "source_se = torch.load(f'{ckpt_base}/zh_default_se.pth').to(device)\n",
    "save_path = f'{output_dir}/output_chinese.wav'\n",
    "\n",
    "# Run the base speaker tts\n",
    "text = \"今天天气真好，我们一起出去吃饭吧。\"\n",
    "src_path = f'{output_dir}/tmp.wav'\n",
    "base_speaker_tts.tts(text, src_path, speaker='default', language='Chinese', speed=1.0)\n",
    "\n",
    "# Run the tone color converter\n",
    "encode_message = \"@MyShell\"\n",
    "tone_color_converter.convert(\n",
    "    audio_src_path=src_path, \n",
    "    src_se=source_se, \n",
    "    tgt_se=target_se, \n",
    "    output_path=save_path,\n",
    "    message=encode_message)"
   ],
   "outputs": [],
   "execution_count": null
  },
  {
   "cell_type": "markdown",
   "id": "8e513094",
   "metadata": {},
   "source": [
    "**Tech for good.** For people who will deploy OpenVoice for public usage: We offer you the option to add watermark to avoid potential misuse. Please see the ToneColorConverter class. **MyShell reserves the ability to detect whether an audio is generated by OpenVoice**, no matter whether the watermark is added or not."
   ]
  }
 ],
 "metadata": {
  "interpreter": {
   "hash": "9d70c38e1c0b038dbdffdaa4f8bfa1f6767c43760905c87a9fbe7800d18c6c35"
  },
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.18"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
